package cs2340.spring13.team3.wheresmystuff.views;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;

import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import cs2340.spring13.team3.wheresmystuff.R;
import cs2340.spring13.team3.wheresmystuff.model.Item;
import cs2340.spring13.team3.wheresmystuff.model.ServerObject;
import cs2340.spring13.team3.wheresmystuff.model.Tag;
import cs2340.spring13.team3.wheresmystuff.model.User;
import cs2340.spring13.team3.wheresmystuff.presenters.LoginManager;
import cs2340.spring13.team3.wheresmystuff.support.ItemSearchDialog;
import cs2340.spring13.team3.wheresmystuff.support.JSONMessage;
import cs2340.spring13.team3.wheresmystuff.support.SearchDialogListener;

/**
 * This class shows a list of all the items that the user has lost.
 * 
 * @author carmen78xy, tswihart3, R Keane
 * @version 0.3
 * 
 */
public class ViewItemListActivity extends Activity implements
		ActionBar.OnNavigationListener {

	/**
	 * The serialization (saved instance state) Bundle key representing the
	 * current dropdown position.
	 */
	public static final int MERGE_SUCCESS = 100;
	public static final int MERGE_FAILURE = 0;
	private User currentUser = LoginManager.getInstance().getUser();
	private ListView lv;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
				.permitAll().build();
		StrictMode.setThreadPolicy(policy);
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_view_lost_items);
		lv = (ListView) findViewById(R.id.lostItemList);

		lv.setAdapter(new ItemListAdapter(this, R.layout.item_list_row,
				currentUser.getItems()));
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.view_lost_items, menu);
		return true;
	}

	public boolean onNavigationItemSelected(int position, long id) {
		// When the given dropdown item is selected, show its contents in the
		// container view.
		// Fragment fragment = new ItemSectionFragment();
		// Bundle args = new Bundle();
		// args.putInt(ItemSectionFragment.ARG_SECTION_NUMBER, position);
		// fragment.setArguments(args);
		// getSupportFragmentManager().beginTransaction()
		// .replace(R.id.container, fragment).commit();
		return true;
	}

	@Override
	public void onResume() {
		super.onResume();
		lv.setAdapter(new ItemListAdapter(this, R.layout.item_list_row,
				currentUser.getItems()));
		lv.invalidateViews();
		lv.requestLayout();
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem menuItem) {
		switch (menuItem.getItemId()) {
		case R.id.action_item_add:
			startActivity(new Intent(getApplicationContext(),
					AddItemActivity.class));
			break;
		case R.id.action_search:
			ItemSearchDialog sd = new ItemSearchDialog(this,
					new SearchListener());
			sd.show();
			// startActivity(new
			// Intent(getApplicationContext(),ViewSearchFilterActivity.class));
			break;
		}
		return false;
	}

	/**
	 * notifies the screen when a sub-activity completes, and performs the
	 * appropriate actions
	 * 
	 * @param source
	 *            The button from which the click originates
	 */
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (resultCode == MERGE_SUCCESS) {
			// do stuff when merge returns (successful), if needed
		}

	}

	/**
	 * Starts the addItemActivity when the user clicks the "add more" button.
	 * 
	 * @param view
	 */
	public void onAddClick(View view) {
		Intent intent = new Intent(this, AddItemActivity.class);
		startActivity(intent);
	}

	/**
	 * An Adapter to render a list of items. Will be separated out into a
	 * fragment eventually (for use as a general item list, for searches, etc.)
	 * 
	 * methods in this class override those of BaseAdapter et. al.
	 * 
	 * In here we reference 'currentUser.getItems()' so that when the user's
	 * item list changes, so too does the view as soon as its drawn
	 * 
	 * @author tswihart3
	 * 
	 */
	public class ItemListAdapter extends BaseAdapter implements Filterable {
		private Activity context;
		private int listResourceId;
		List<Item> items;
		private ItemListFilter mFilter;

		public ItemListAdapter(Activity ctx, int resId, List<Item> items) {
			this.context = ctx;
			this.listResourceId = resId;
			this.items = items;
		}

		public int getCount() {
			return items.size();
		}

		public Item getItem(int arg0) {
			return items.get(arg0);
		}

		public long getItemId(int position) {
			return position;
		}

		@SuppressLint("SimpleDateFormat")
		public View getView(int position, View convertView, ViewGroup parent) {
			Item i = items.get(position);
			System.out.println(items.get(position).getDate());
			View itemRow = (LinearLayout) convertView;
			if (convertView == null) {
				itemRow = (LinearLayout) context.getLayoutInflater().inflate(
						listResourceId, parent, false);
			}

			TextView itemName = (TextView) itemRow.findViewById(R.id.itemName);
			itemName.setText(i.getName());
			TextView itemDate = (TextView) itemRow.findViewById(R.id.itemDate);
			itemDate.setText(new SimpleDateFormat("yyyy-MM-dd").format(i
					.getDate()));
			TextView itemStub = (TextView) itemRow.findViewById(R.id.itemStub);
			itemStub.setText(i.getDescription());
			TextView itemMatch = (TextView) itemRow
					.findViewById(R.id.itemMatch);
			itemMatch
					.setText(i.getMatchName() == Item.DEFAULT_MATCH
							|| (i.getMatchName().equals(Item.DEFAULT_MATCH)) ? "Unmatched"
							: "Match: " + i.getMatchName());
			ImageView itemIcon = (ImageView) itemRow
					.findViewById(R.id.itemIcon);
			itemIcon.setImageDrawable(getResources().getDrawable(
					(i.getMatchName() == Item.DEFAULT_MATCH || (i
							.getMatchName().equals(Item.DEFAULT_MATCH))) ? (i
							.getFound() ? android.R.drawable.ic_input_add
							: android.R.drawable.ic_delete)
							: android.R.drawable.ic_menu_myplaces));
			Button b = (Button) itemRow.findViewById(R.id.selectMatchButton);
			/*
			 * if (LoginManager.getInstance().getUser() != null &&
			 * LoginManager.getInstance().getUser().getItems() .contains(i)) {
			 * b.setVisibility(Button.INVISIBLE); b.setClickable(false); } else
			 * {
			 */b.setOnClickListener(new MatchListener(this.context, i));
			// }

			return itemRow;
		}

		@Override
		public Filter getFilter() {
			if (mFilter == null) {
				mFilter = new ItemListFilter();
			}
			return mFilter;
		}

	}

	private class ItemListFilter extends Filter {

		@Override
		protected FilterResults performFiltering(CharSequence constraint) {
			String constraintString = constraint.toString();

			FilterResults results = new FilterResults();
			results.values = currentUser.getItems();
			results.count = currentUser.getItems().size();

			if (!(constraintString == null || constraintString.length() == 0)) {
				// We perform filtering operation
				List<Item> nItemList = new ArrayList<Item>();
				List<Item> items = currentUser.getItems();

				boolean isFound = true;
				if (constraintString == "status: lost") {
					isFound = false;
				}
				for (Item i : items) {
					if (i.getFound() == isFound)
						nItemList.add(i);
				}

				results.values = nItemList;
				results.count = nItemList.size();

			}
			return results;
		}

		@SuppressWarnings("unchecked")
		@Override
		protected void publishResults(CharSequence constraint,
				FilterResults results) {
			// Now we have to inform the adapter about the new list filtered
			if (results.count != 0) {
				lv.setAdapter(new ItemListAdapter(ViewItemListActivity.this,
						R.layout.item_list_row, (List<Item>) results.values));
				lv.invalidateViews();
				lv.requestLayout();
			} else {
				lv.setAdapter(new ItemListAdapter(ViewItemListActivity.this,
						R.layout.item_list_row, currentUser.getItems()));
				lv.invalidateViews();
				lv.requestLayout();
			}

		}

		@SuppressWarnings("unused")
		public void filter(String searchText, Boolean isFound) {

			FilterResults results = new FilterResults();
			List<Item> items = currentUser.getItems();
			List<Item> nItemList = new ArrayList<Item>();

			if (searchText != null && searchText.length() > 0) {
				String[] tags = searchText.split(",");
				List<Tag> itemTagList = new ArrayList<Tag>();
				for (String tag : tags) {
					Tag newTag = new Tag();
					newTag.setTitle(tag);
					itemTagList.add(newTag);
				}

				for (Item i : items) {
					if (itemTagList.size() > 0) {
						for (Tag t : itemTagList) {
							if (i.getTags().contains(t)) {
								if (i.getFound() == isFound) {
									nItemList.add(i);
								}
							}
						}
					}
				}
				results.values = nItemList;
				results.count = nItemList.size();
			} else if (isFound != null) {
				for (Item i : items) {
					if (i.getFound() == isFound) {
						nItemList.add(i);
					}
				}

			} else {
				nItemList = items;
			}
			lv.setAdapter(new ItemListAdapter(ViewItemListActivity.this,
					R.layout.item_list_row, nItemList));
			lv.invalidateViews();
			lv.requestLayout();
		}
	}

	public void showSearchResults(List<Item> results) {
		if (results != null) {
			lv.setAdapter(new ItemListAdapter(ViewItemListActivity.this,
					R.layout.item_list_row, results));
			lv.invalidateViews();
			lv.requestLayout();
		} else {
			lv.setAdapter(new ItemListAdapter(ViewItemListActivity.this,
					R.layout.item_list_row, currentUser.getItems()));
			lv.invalidateViews();
			lv.requestLayout();
		}
	}

	public List<Item> search(String name, String tag, Boolean isLost) {
		List<Item> results = null;
		if (isLost != null) {
			try {
				if ((name == null || name.isEmpty())
						&& (tag == null || tag.isEmpty()))
					return results;

				HttpGet searchGet;
				if (name == null || name.isEmpty()) {
					// Log.w("TRYING GET REQUEST",
					// "https://immense-temple-7838.herokuapp.com/items?tag=" +
					// URLEncoder.encode(tag, "utf-8"));
					searchGet = new HttpGet(new URI(
							"https://immense-temple-7838.herokuapp.com/items?tag="
									+ URLEncoder.encode(tag, "utf-8")));
				} else if (tag == null || tag.isEmpty()) {
					// Log.w("TRYING GET REQUEST",
					// "https://immense-temple-7838.herokuapp.com/items?name=" +
					// URLEncoder.encode(name, "utf-8"));
					searchGet = new HttpGet(new URI(
							"https://immense-temple-7838.herokuapp.com/items?name="
									+ URLEncoder.encode(name, "utf-8")));
				} else {
					// Log.w("TRYING GET REQUEST",
					// "https://immense-temple-7838.herokuapp.com/items?name=" +
					// URLEncoder.encode(name, "utf-8") + "&tag=" +
					// URLEncoder.encode(tag, "utf-8"));
					searchGet = new HttpGet(
							new URI(
									"https://immense-temple-7838.herokuapp.com/items?name="
											+ URLEncoder.encode(name, "utf-8")
											+ "&tag="
											+ URLEncoder.encode(tag, "utf-8")));
				}
				HttpResponse response;
				response = ServerObject.getHttp().execute(searchGet);
				InputStream is = response.getEntity().getContent();
				ObjectMapper mapper = new ObjectMapper();
				JSONMessage msg = new JSONMessage(mapper.readValue(is,
						JsonNode.class));
				if (msg.getErr().length() > 0 && msg.getErr() != "null") {
					// handle error from server
				} else {
					results = new ArrayList<Item>();
					JsonNode node = msg.getObj();
					Iterator<JsonNode> iterator = node.getElements();
					while (iterator.hasNext()) {
						results.add(new Item(iterator.next()));
					}

				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (URISyntaxException e) {
				e.printStackTrace();
			}
		}
		return results;

	}

	private class SearchListener implements SearchDialogListener {

		@Override
		public void onOkClick(String name, String tags, Boolean isLost) {
			/*
			 * ((ItemListFilter) ((ItemListAdapter)
			 * lv.getAdapter()).getFilter()) .filter(searchText, isLost);
			 */
			showSearchResults(search(name, tags, isLost));

		}

	}

	private class MatchListener implements OnClickListener {
		private Item i;
		Activity ct;

		public MatchListener(Activity a, Item j) {
			i = j;
			ct = a;
		}

		public void onClick(View v) {
			Intent intent = new Intent(ct, MatchItemActivity.class);
			HashMap<Long, Item> map = new HashMap<Long, Item>();
			map.put(MatchItemActivity.MAP_PASSING_INDEX, i);
			intent.putExtra("map", map);
			startActivityForResult(intent, MERGE_SUCCESS);
		}

	}

}
